from pyson import as_str_path

class ValidationError(ValueError):
    '''Base exception raised by schema operations.'''

    def __init__(self, msg='on path: {path}', path=None, meta=None, **kwds):
        '''Raised when something goes wrong with a schema operation (validation, 
        adaptation, etc). SchemaError instances have an additional 'path' 
        attribute that describe the path in which the error occurred.
        '''

        meta = meta if meta is not None else {}
        meta.update(kwds)
        args = (msg, path, meta)
        super(ValidationError, self).__init__(*args)

        self.path = list(path) if path is not None else []
        self.message = msg
        self.meta = meta

    def __getattr__(self, attr):
        try:
            return self.meta[attr]
        except KeyError:
            raise AttributeError(attr)

    def __str__(self):
        if '{path}' not in self.message and self.path:
            message = '{path}: ' + self.message
        else:
            message = self.message
        if not self.path:
            stpath = '<root>'
        else:
            stpath = as_str_path(self.path)

        return message.format(path=stpath, **self.meta)

    def __unicode__(self):
        return unicode(str(self))

class NoRootError(Exception):
    '''Raised when a root validation is requested from a schema that has no
    root nodes'''
    pass

class AdaptationError(ValidationError):
    pass

if __name__ == '__main__':
    import doctest
    doctest.testmod(optionflags=doctest.REPORT_ONLY_FIRST_FAILURE, verbose=0)

